package cn.zf233.jwtshiro.web;

import cn.zf233.jwtshiro.common.R;
import cn.zf233.jwtshiro.config.shiro.open.OpenToken;
import cn.zf233.jwtshiro.config.shiro.sms.VCodeToken;
import cn.zf233.jwtshiro.entity.User;
import cn.zf233.jwtshiro.service.UserService;
import cn.zf233.jwtshiro.util.JwtUtil;
import cn.zf233.jwtshiro.util.TestVCodePool;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * Created by zf233 on 2021/7/12
 */
@Slf4j
@RestController
public class LoginController extends BaseController {

    @Resource
    private UserService userService;

    @PostMapping("/login")
    public R<String> login(User user) {
        log.info("开始进行账号密码登陆:" + user);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
        try {
            subject.login(token);
            User principal = (User) subject.getPrincipal();
            String tokenByUserId = JwtUtil.createTokenByUserId(principal.getId(), TimeUnit.DAYS.toMillis(7L));
            log.info("账号密码登陆成功");
            return R.createBySuccess("普通登陆成功", tokenByUserId);
        } catch (AuthenticationException e) {
            log.info("账号密码登陆失败，错误信息:" + e.getMessage());
            return R.createByErrorMessage(e.getMessage());
        }
    }

    @PostMapping("/login/phone")
    public R<String> loginPhone(User user, String code) {
        log.info("开始进行手机验证码登陆:" + user);
        Subject subject = SecurityUtils.getSubject();
        VCodeToken vCodeToken = new VCodeToken(user.getPhone(), code);
        try {
            subject.login(vCodeToken);
            User principal = (User) subject.getPrincipal();
            String tokenByUserId = JwtUtil.createTokenByUserId(principal.getId(), TimeUnit.DAYS.toMillis(7L));
            log.info("手机验证码登陆成功");
            return R.createBySuccess("验证码登陆成功", tokenByUserId);
        } catch (AuthenticationException e) {
            log.info("手机验证码登陆失败，错误信息:" + e.getMessage());
            return R.createByErrorMessage(e.getMessage());
        }
    }

    @GetMapping("/login/code")
    public R<String> code(User user) {
        log.info("获取手机验证码:" + user);
        User result = userService.getUserByPhone(user.getPhone());
        if (result != null) {
            String code = getVCode();
            TestVCodePool.Set(result.getPhone(), code);
            log.info("获取手机验证码成功:'" + code + "'");
            return R.createBySuccess("手机验证码获取成功", code);
        }
        log.info("用户不存在，获取验证码失败");
        return R.createByErrorMessage("用户不存在");
    }

    @PostMapping("/login/open")
    public R<String> loginOpen(User user) {
        log.info("开始进行社交登陆:" + user);
        Subject subject = SecurityUtils.getSubject();
        OpenToken openToken = new OpenToken(user.getOpenId());
        try {
            subject.login(openToken);
            User principal = (User) subject.getPrincipal();
            String tokenByUserId = JwtUtil.createTokenByUserId(principal.getId(), TimeUnit.DAYS.toMillis(7L));
            log.info("社交登陆成功");
            return R.createBySuccess("社交登陆成功", tokenByUserId);
        } catch (AuthenticationException e) {
            log.info("社交登陆失败，错误信息:" + e.getMessage());
            return R.createByErrorMessage(e.getMessage());
        }
    }

    private String getVCode() {
        log.info("生成验证码");
        StringBuilder code = new StringBuilder();
        // 这里的code可以存入redis
        Random random = new Random();
        for (int i = 0; i < 6; i++) {
            code.append(random.nextInt(10));
        }
        return code.toString();
    }
}
